/*
 * Copyright (c) 2003-2004, Inversoft, All Rights Reserved
 *
 * This software is distribuable under the GNU Lesser General Public License.
 * For more information visit gnu.org.
 */
package org.emergent.antbite.savant;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * <p>
 * This class is the object that stores all the information
 * about dependencies. Usually these objects are scoped to a
 * single project.
 * </p>
 *
 * @author Brian Pontarelli
 */
public class Dependencies {
    private Map projects = new HashMap();
    private List artifactGroups = new ArrayList();
    private List artifacts = new ArrayList();



    /**
     * Fetches the local project for the given ID.
     *
     * @param   id The id of the project to lookup
     */
    public LocalProject getProject(String id) {
        return (LocalProject) projects.get(id);
    }

    /**
     * Adds the given project to the list of local projects. These might be built
     * during the course of mediation if artifacts are produced from these projects.
     * This also calls the {@link LocalProject#validate()} method.
     *
     * @param   project The project to add
     */
    public void addProject(LocalProject project) throws SavantException {
        project.validate();
        projects.put(project.getID(), project);
    }

    /**
     * Removes the given project to the list of local projects.
     *
     * @param   project The project to remove
     */
    public void removeProject(LocalProject project) {
        projects.remove(project.getID());
    }

    /**
     * Adds the given artifact group to the list of artifact groups to mediate
     * over. This group is validated by calling the {@link ArtifactGroup#validate()}
     * method.
     *
     * @param   group The group to add
     */
    public void addArtifactGroup(ArtifactGroup group) throws SavantException {
        group.validate();
        this.artifactGroups.add(group);
    }

    /**
     * Removes the given artifact group to the list of artifact groups in this
     * dependency.
     *
     * @param   group The group to remove
     */
    public void removeArtifactGroup(ArtifactGroup group) {
        this.artifactGroups.remove(group);
    }

    /**
     * Adds the given artifact to the list of artifact to mediate over. This
     * artifact is validated by calling the {@link Artifact#validate()}
     * method.
     *
     * @param   artifact The artifact to add
     */
    public void addArtifact(Artifact artifact) throws SavantException {
        artifact.validate();
        this.artifacts.add(artifact);
    }

    /**
     * Removes the given artifact to the list of artifact in this dependency.
     *
     * @param   artifact The artifact to remove
     */
    public void removeArtifact(Artifact artifact) {
        this.artifacts.add(artifact);
    }

    /**
     * Returns the artifact group list. This is list immutable.
     */
    public List getArtifactGroups() {
        return Collections.unmodifiableList(artifactGroups);
    }

    /**
     * Returns the artifact list. This List is immutable.
     */
    public List getArtifacts() {
        return artifacts;
    }

    /**
     * Returns the Set of artifacts contained here or in ArtifactGroups within.
     * This never returns null.
     */
    public Set getAllArtifacts() {
        Set set = new HashSet();
        for (int i = 0; i < artifactGroups.size(); i++) {
            ArtifactGroup group = (ArtifactGroup) artifactGroups.get(i);
            addGroup(set, group);
        }

        set.addAll(artifacts);

        return set;
    }

    /**
     * Recursive method that adds the artifacts from an ArtifacGroup and recurses
     * into each sub-group.
     *
     * @param   set The Set to store the artifacts in.
     * @param   group The group to add the artifacts from.
     */
    protected void addGroup(Set set, ArtifactGroup group) {
        set.addAll(group.getArtifacts());

        List groups = group.getArtifactGroups();
        for (int i = 0; i < groups.size(); i++) {
            addGroup(set, (ArtifactGroup) groups.get(i));

        }
    }
}